package main

// 79. 单词搜索
func main() {
	board := [][]byte{[]byte("ABCE"), []byte("SFCS"), []byte("ADEE")}
	word := "ABCCED"

	b := exist(board, word)
	println(b)
}

func exist(board [][]byte, word string) bool {
	var has bool
	wordBytes := []byte(word)
	wordBytesLen := len(wordBytes)
	if len(board) == 0 || len(board[0]) == 0 {
		return false
	}
	height := len(board)
	length := len(board[0])

	visited := make([][]bool, height)
	for i := range visited {
		visited[i] = make([]bool, length)
	}

	var dfs func(i, j, idx int) bool
	dfs = func(i, j, idx int) bool {
		// 上下左右回溯，记录访问状态，注意边界，进来直接处理边界
		if (i < 0 || i > height-1) || (j < 0 || j > length-1) || visited[i][j] {
			return false
		}
		if idx == wordBytesLen-1 && board[i][j] == wordBytes[idx] {
			return true
		}
		if board[i][j] == wordBytes[idx] {
			visited[i][j] = true
			topRes := dfs(i-1, j, idx+1)
			rightRes := dfs(i, j+1, idx+1)
			bottomRes := dfs(i+1, j, idx+1)
			leftRes := dfs(i, j-1, idx+1)
			visited[i][j] = false
			if topRes || rightRes || bottomRes || leftRes {
				return true
			}
		}
		return false
	}

	for h := 0; h < height; h++ {
		for l := 0; l < length; l++ {
			has = dfs(h, l, 0)
			if has {
				return has
			}
		}
	}

	return has
}

// 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中，返回 true ；否则，返回 false 。
//
//单词必须按照字母顺序，通过相邻的单元格内的字母构成，其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
// 输入：board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
//输出：true
